package com.aboo.design.chain;

import com.alibaba.fastjson2.JSON;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 责任链模式
 * 避免请求发送者与接收者耦合在一起，让多个对象都有可能接收请求，将这些对象连接成一条链，并且沿着这条链传递请求，直到有对象处理它为止。
 *
 * @author louan
 * @date 2023/12/2
 */
public class ChainPattern {

    public static void main(String[] args) {
        ChainHandler.process(new UserInfo("", 15, "F"));
        System.out.println("============================");

        ChainHandler.process(new UserInfo("张三", 120, "S"));
        System.out.println("============================");

        ChainHandler.process(new UserInfo("李四", 35, "O"));
        System.out.println("============================");

        ChainHandler.process(new UserInfo("王五", 22, "F"));
        System.out.println("============================");

        ChainHandler.process(new UserInfo(null, -1, "X"));
        System.out.println("============================");
    }
}

class ChainHandler {

    private static final List<Handler> HANDLER_LIST = new ArrayList<>(8);

    static {
        List<Handler> handlers = new ArrayList<>(8);
        handlers.add(new CheckNameHandler());
        handlers.add(new CheckAgeHandler());
        handlers.add(new CheckSexHandler());
        handlers.add(new DefaultHandler());
        handlers = handlers.stream().sorted(Comparator.comparingInt(Handler::priority)).collect(Collectors.toList());
        for (int i = 0; i < handlers.size() - 1; i++) {
            handlers.get(i).setNext(handlers.get(i + 1));
            HANDLER_LIST.add(handlers.get(i));
        }
    }

    public static void process(UserInfo userInfo) {
        Handler handler = HANDLER_LIST.get(0);
        boolean result;
        do {
            result = handler.handle(userInfo);
            if (result) {
                break;
            }
            handler = handler.getNext();
        } while (handler != null);
    }
}

abstract class Handler {

    protected Handler nextHandler;

    public void setNext(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public Handler getNext() {
        return this.nextHandler;
    }

    abstract int priority();

    abstract boolean handle(UserInfo userInfo);

}

class CheckNameHandler extends Handler {
    @Override
    public int priority() {
        return 1;
    }

    @Override
    public boolean handle(UserInfo userInfo) {
        if (StringUtils.isBlank(userInfo.getName())) {
            System.out.println("用户姓名不能为空:" + JSON.toJSONString(userInfo));
            return true;
        }

        return false;
    }
}

class CheckAgeHandler extends Handler {
    @Override
    public int priority() {
        return 2;
    }

    @Override
    public boolean handle(UserInfo userInfo) {
        if (userInfo.getAge() == null || userInfo.getAge() <= 0 || userInfo.getAge() > 100) {
            System.out.println("用户年龄不合法:" + JSON.toJSONString(userInfo));
            return true;
        }

        return false;
    }
}

class CheckSexHandler extends Handler {
    @Override
    public int priority() {
        return 3;
    }

    @Override
    public boolean handle(UserInfo userInfo) {
        if (StringUtils.isBlank(userInfo.getSex()) || !List.of("F", "M").contains(userInfo.getSex())) {
            System.out.println("用户性别不合法:" + JSON.toJSONString(userInfo));
            return true;
        }

        return false;
    }
}

class DefaultHandler extends Handler {
    @Override
    public int priority() {
        return 4;
    }

    @Override
    public boolean handle(UserInfo userInfo) {
        System.out.println("用户信息合法:" + JSON.toJSONString(userInfo));
        return true;
    }
}

@Data
class UserInfo {

    private String name;
    private Integer age;
    private String sex;

    public UserInfo(String name, Integer age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
}